/*
 * ecb_crypt, cbc_crypt, des_setparity - DES encryption/decryption routine
 *
 *	Written by Koichiro Mori (kmori@lsi-j.co.jp)
 */
#include <string.h>
#include "../systeminc/version.h"
#include "descrypt.h"

#define	YES	1
#define	NO	0
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef	unsigned int uint;
typedef unsigned long ulong;




void des_setparity(char *key)
{
	int n;

	for (n = 8; n > 0; n--) {
		char c;

		c = *key &= 0x7f;
		c ^= c << 4;
		c ^= c << 2;
		c ^= c << 1;
		*key++ ^= ~c & 0x80;
	}
}


ulong Keys[16][2];

void des_setkey(char *key)
{
	static char nshifts[]
		= { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
#define	C	28
#define	D	0
	static uchar pc1[] = {
		C + 20, C + 12, C + 4, D + 0, D + 4, D + 12, D + 20,
		C + 21, C + 13, C + 5, D + 1, D + 5, D + 13, D + 21,
		C + 22, C + 14, C + 6, D + 2, D + 6, D + 14, D + 22,
		C + 23, C + 15, C + 7, D + 3, D + 7, D + 15, D + 23,
		C + 24, C + 16, C + 8, C + 0, D + 8, D + 16, D + 24,
		C + 25, C + 17, C + 9, C + 1, D + 9, D + 17, D + 25,
		C + 26, C + 18, C +10, C + 2, D +10, D + 18, D + 26,
		C + 27, C + 19, C +11, C + 3, D +11, D + 19, D + 27
	};
	static uchar pc2_c[] = {
		14, 11, 17,  4, 27, 23,
		25,  0, 13, 22,  7, 18,
		 5,  9, 16, 24,  2, 20,
		12, 21,  1,  8, 15, 26
	};
	static uchar pc2_d[] = {
		15,  4, 25, 19,  9,  1,
		26, 16,  5, 11, 23,  8,
		12,  7, 17,  0, 22,  3,
		10, 14,  6, 20, 27, 24,
	};
	ulong c, d;
	uchar b, *p;
	int i, j;

	/* PC-1 (Permuted Choice 1) */
	c = d = 0;
	p = pc1;
	for (i = 0; i < 8; i++) {
		b = *key++;
		for (j = 0; j < 7; j++) {
			if (b & 0x80) {
				if (*p >= C)
					c |= 1L << (*p - C);
				else
					d |= 1L << *p;
			}
			p++;
			b <<= 1;
		}
	}

	for (i = 0; i < 16; i++) {
		uchar *k, mask, w[8];
		uint n = nshifts[i];
		
		c = (c << n | c >> (28 - n)) & 0x0fffffff;
		d = (d << n | d >> (28 - n)) & 0x0fffffff;
		/* PC-2 (Permuted Choice 2) */
		k = w;
		p = pc2_c;
		for (j = 0; j < 4; j++) {
			*k = 0;
			for (mask = 0x20; mask > 0; mask >>= 1) {
				if ((c >> *p++) & 1)
					*k |= mask;
			}
			k++;
		}
		p = pc2_d;
		for (j = 0; j < 4; j++) {
			*k = 0;
			for (mask = 0x20; mask > 0; mask >>= 1) {
				if ((d >> *p++) & 1)
					*k |= mask;
			}
			k++;
		}

		Keys[i][0] = ((ulong)w[0] << 24) | ((ulong)w[2] << 16)
			   | ((ulong)w[4] << 8) | (ulong)w[6];
		Keys[i][1] = ((ulong)w[1] << 24) | ((ulong)w[3] << 16)
			   | ((ulong)w[5] << 8) | (ulong)w[7];

	}
}





#if MSC
#define	ror4(x) _lrotr(x, 4)
#define	rol1(x) _lrotl(x, 1)

#else
#define	ror4(x)	((x) >> 4 | (x) << 28)
#define	rol1(x)	((x) << 1 | (x) >> 31)

#endif


#if SMALL
uchar Sboxes[8][64] = {
	{
	14,  0,  4, 15, 13,  7,  1,  4,  2, 14, 15,  2, 11, 13,  8,  1,
	 3, 10, 10,  6,  6, 12, 12, 11,  5,  9,  9,  5,  0,  3,  7,  8,
	 4, 15,  1, 12, 14,  8,  8,  2, 13,  4,  6,  9,  2,  1, 11,  7,
	15,  5, 12, 11,  9,  3,  7, 14,  3, 10, 10,  0,  5,  6,  0, 13,
	},
	{
	15,  3,  1, 13,  8,  4, 14,  7,  6, 15, 11,  2,  3,  8,  4, 14,
	 9, 12,  7,  0,  2,  1, 13, 10, 12,  6,  0,  9,  5, 11, 10,  5,
	 0, 13, 14,  8,  7, 10, 11,  1, 10,  3,  4, 15, 13,  4,  1,  2,
	 5, 11,  8,  6, 12,  7,  6, 12,  9,  0,  3,  5,  2, 14, 15,  9,
	},
	{
	10, 13,  0,  7,  9,  0, 14,  9,  6,  3,  3,  4, 15,  6,  5, 10,
	 1,  2, 13,  8, 12,  5,  7, 14, 11, 12,  4, 11,  2, 15,  8,  1,
	13,  1,  6, 10,  4, 13,  9,  0,  8,  6, 15,  9,  3,  8,  0,  7,
	11,  4,  1, 15,  2, 14, 12,  3,  5, 11, 10,  5, 14,  2,  7, 12,
	},
	{
	 7, 13, 13,  8, 14, 11,  3,  5,  0,  6,  6, 15,  9,  0, 10,  3,
	 1,  4,  2,  7,  8,  2,  5, 12, 11,  1, 12, 10,  4, 14, 15,  9,
	10,  3,  6, 15,  9,  0,  0,  6, 12, 10, 11,  1,  7, 13, 13,  8,
	15,  9,  1,  4,  3,  5, 14, 11,  5, 12,  2,  7,  8,  2,  4, 14,
	},
	{
	 2, 14, 12, 11,  4,  2,  1, 12,  7,  4, 10,  7, 11, 13,  6,  1,
	 8,  5,  5,  0,  3, 15, 15, 10, 13,  3,  0,  9, 14,  8,  9,  6,
	 4, 11,  2,  8,  1, 12, 11,  7, 10,  1, 13, 14,  7,  2,  8, 13,
	15,  6,  9, 15, 12,  0,  5,  9,  6, 10,  3,  4,  0,  5, 14,  3,
	},
	{
	12, 10,  1, 15, 10,  4, 15,  2,  9,  7,  2, 12,  6,  9,  8,  5,
	 0,  6, 13,  1,  3, 13,  4, 14, 14,  0,  7, 11,  5,  3, 11,  8,
	 9,  4, 14,  3, 15,  2,  5, 12,  2,  9,  8,  5, 12, 15,  3, 10,
	 7, 11,  0, 14,  4,  1, 10,  7,  1,  6, 13,  0, 11,  8,  6, 13,
	},
	{
	 4, 13, 11,  0,  2, 11, 14,  7, 15,  4,  0,  9,  8,  1, 13, 10,
	 3, 14, 12,  3,  9,  5,  7, 12,  5,  2, 10, 15,  6,  8,  1,  6,
	 1,  6,  4, 11, 11, 13, 13,  8, 12,  1,  3,  4,  7, 10, 14,  7,
	10,  9, 15,  5,  6,  0,  8, 15,  0, 14,  5,  2,  9,  3,  2, 12,
	},
	{
	13,  1,  2, 15,  8, 13,  4,  8,  6, 10, 15,  3, 11,  7,  1,  4,
	10, 12,  9,  5,  3,  6, 14, 11,  5,  0,  0, 14, 12,  9,  7,  2,
	 7,  2, 11,  1,  4, 14,  1,  7,  9,  4, 12, 10, 14,  8,  2, 13,
	 0, 15,  6, 12, 10,  9, 13,  0, 15,  3,  3,  5,  5,  6,  8, 11,
	},
};

ulong Ptbl[8][16] = {
	{
	0x00000000, 0x00000002, 0x00000200, 0x00000202,
	0x00008000, 0x00008002, 0x00008200, 0x00008202,
	0x00800000, 0x00800002, 0x00800200, 0x00800202,
	0x00808000, 0x00808002, 0x00808200, 0x00808202,
	},
	{
	0x00000000, 0x00004000, 0x40000000, 0x40004000,
	0x00000010, 0x00004010, 0x40000010, 0x40004010,
	0x00080000, 0x00084000, 0x40080000, 0x40084000,
	0x00080010, 0x00084010, 0x40080010, 0x40084010,
	},
	{
	0x00000000, 0x04000000, 0x00000004, 0x04000004,
	0x00010000, 0x04010000, 0x00010004, 0x04010004,
	0x00000100, 0x04000100, 0x00000104, 0x04000104,
	0x00010100, 0x04010100, 0x00010104, 0x04010104,
	},
	{
	0x00000000, 0x80000000, 0x00400000, 0x80400000,
	0x00001000, 0x80001000, 0x00401000, 0x80401000,
	0x00000040, 0x80000040, 0x00400040, 0x80400040,
	0x00001040, 0x80001040, 0x00401040, 0x80401040,
	},
	{
	0x00000000, 0x20000000, 0x00000080, 0x20000080,
	0x00040000, 0x20040000, 0x00040080, 0x20040080,
	0x01000000, 0x21000000, 0x01000080, 0x21000080,
	0x01040000, 0x21040000, 0x01040080, 0x21040080,
	},
	{
	0x00000000, 0x00002000, 0x00200000, 0x00202000,
	0x00000008, 0x00002008, 0x00200008, 0x00202008,
	0x10000000, 0x10002000, 0x10200000, 0x10202000,
	0x10000008, 0x10002008, 0x10200008, 0x10202008,
	},
	{
	0x00000000, 0x02000000, 0x00000400, 0x02000400,
	0x00100000, 0x02100000, 0x00100400, 0x02100400,
	0x00000001, 0x02000001, 0x00000401, 0x02000401,
	0x00100001, 0x02100001, 0x00100401, 0x02100401,
	},
	{
	0x00000000, 0x00000800, 0x00020000, 0x00020800,
	0x00000020, 0x00000820, 0x00020020, 0x00020820,
	0x08000000, 0x08000800, 0x08020000, 0x08020800,
	0x08000020, 0x08000820, 0x08020020, 0x08020820,
	},
};

#define	ps(i, j)	Ptbl[i][Sboxes[i][j]]

#else /* MIDDLE */

ulong Psboxes[8][64] = {
	{
	0x00808200, 0x00000000, 0x00008000, 0x00808202,
	0x00808002, 0x00008202, 0x00000002, 0x00008000,
	0x00000200, 0x00808200, 0x00808202, 0x00000200,
	0x00800202, 0x00808002, 0x00800000, 0x00000002,
	0x00000202, 0x00800200, 0x00800200, 0x00008200,
	0x00008200, 0x00808000, 0x00808000, 0x00800202,
	0x00008002, 0x00800002, 0x00800002, 0x00008002,
	0x00000000, 0x00000202, 0x00008202, 0x00800000,
	0x00008000, 0x00808202, 0x00000002, 0x00808000,
	0x00808200, 0x00800000, 0x00800000, 0x00000200,
	0x00808002, 0x00008000, 0x00008200, 0x00800002,
	0x00000200, 0x00000002, 0x00800202, 0x00008202,
	0x00808202, 0x00008002, 0x00808000, 0x00800202,
	0x00800002, 0x00000202, 0x00008202, 0x00808200,
	0x00000202, 0x00800200, 0x00800200, 0x00000000,
	0x00008002, 0x00008200, 0x00000000, 0x00808002,
	},
	{
	0x40084010, 0x40004000, 0x00004000, 0x00084010,
	0x00080000, 0x00000010, 0x40080010, 0x40004010,
	0x40000010, 0x40084010, 0x40084000, 0x40000000,
	0x40004000, 0x00080000, 0x00000010, 0x40080010,
	0x00084000, 0x00080010, 0x40004010, 0x00000000,
	0x40000000, 0x00004000, 0x00084010, 0x40080000,
	0x00080010, 0x40000010, 0x00000000, 0x00084000,
	0x00004010, 0x40084000, 0x40080000, 0x00004010,
	0x00000000, 0x00084010, 0x40080010, 0x00080000,
	0x40004010, 0x40080000, 0x40084000, 0x00004000,
	0x40080000, 0x40004000, 0x00000010, 0x40084010,
	0x00084010, 0x00000010, 0x00004000, 0x40000000,
	0x00004010, 0x40084000, 0x00080000, 0x40000010,
	0x00080010, 0x40004010, 0x40000010, 0x00080010,
	0x00084000, 0x00000000, 0x40004000, 0x00004010,
	0x40000000, 0x40080010, 0x40084010, 0x00084000,
	},
	{
	0x00000104, 0x04010100, 0x00000000, 0x04010004,
	0x04000100, 0x00000000, 0x00010104, 0x04000100,
	0x00010004, 0x04000004, 0x04000004, 0x00010000,
	0x04010104, 0x00010004, 0x04010000, 0x00000104,
	0x04000000, 0x00000004, 0x04010100, 0x00000100,
	0x00010100, 0x04010000, 0x04010004, 0x00010104,
	0x04000104, 0x00010100, 0x00010000, 0x04000104,
	0x00000004, 0x04010104, 0x00000100, 0x04000000,
	0x04010100, 0x04000000, 0x00010004, 0x00000104,
	0x00010000, 0x04010100, 0x04000100, 0x00000000,
	0x00000100, 0x00010004, 0x04010104, 0x04000100,
	0x04000004, 0x00000100, 0x00000000, 0x04010004,
	0x04000104, 0x00010000, 0x04000000, 0x04010104,
	0x00000004, 0x00010104, 0x00010100, 0x04000004,
	0x04010000, 0x04000104, 0x00000104, 0x04010000,
	0x00010104, 0x00000004, 0x04010004, 0x00010100,
	},
	{
	0x80401000, 0x80001040, 0x80001040, 0x00000040,
	0x00401040, 0x80400040, 0x80400000, 0x80001000,
	0x00000000, 0x00401000, 0x00401000, 0x80401040,
	0x80000040, 0x00000000, 0x00400040, 0x80400000,
	0x80000000, 0x00001000, 0x00400000, 0x80401000,
	0x00000040, 0x00400000, 0x80001000, 0x00001040,
	0x80400040, 0x80000000, 0x00001040, 0x00400040,
	0x00001000, 0x00401040, 0x80401040, 0x80000040,
	0x00400040, 0x80400000, 0x00401000, 0x80401040,
	0x80000040, 0x00000000, 0x00000000, 0x00401000,
	0x00001040, 0x00400040, 0x80400040, 0x80000000,
	0x80401000, 0x80001040, 0x80001040, 0x00000040,
	0x80401040, 0x80000040, 0x80000000, 0x00001000,
	0x80400000, 0x80001000, 0x00401040, 0x80400040,
	0x80001000, 0x00001040, 0x00400000, 0x80401000,
	0x00000040, 0x00400000, 0x00001000, 0x00401040,
	},
	{
	0x00000080, 0x01040080, 0x01040000, 0x21000080,
	0x00040000, 0x00000080, 0x20000000, 0x01040000,
	0x20040080, 0x00040000, 0x01000080, 0x20040080,
	0x21000080, 0x21040000, 0x00040080, 0x20000000,
	0x01000000, 0x20040000, 0x20040000, 0x00000000,
	0x20000080, 0x21040080, 0x21040080, 0x01000080,
	0x21040000, 0x20000080, 0x00000000, 0x21000000,
	0x01040080, 0x01000000, 0x21000000, 0x00040080,
	0x00040000, 0x21000080, 0x00000080, 0x01000000,
	0x20000000, 0x01040000, 0x21000080, 0x20040080,
	0x01000080, 0x20000000, 0x21040000, 0x01040080,
	0x20040080, 0x00000080, 0x01000000, 0x21040000,
	0x21040080, 0x00040080, 0x21000000, 0x21040080,
	0x01040000, 0x00000000, 0x20040000, 0x21000000,
	0x00040080, 0x01000080, 0x20000080, 0x00040000,
	0x00000000, 0x20040000, 0x01040080, 0x20000080,
	},
	{
	0x10000008, 0x10200000, 0x00002000, 0x10202008,
	0x10200000, 0x00000008, 0x10202008, 0x00200000,
	0x10002000, 0x00202008, 0x00200000, 0x10000008,
	0x00200008, 0x10002000, 0x10000000, 0x00002008,
	0x00000000, 0x00200008, 0x10002008, 0x00002000,
	0x00202000, 0x10002008, 0x00000008, 0x10200008,
	0x10200008, 0x00000000, 0x00202008, 0x10202000,
	0x00002008, 0x00202000, 0x10202000, 0x10000000,
	0x10002000, 0x00000008, 0x10200008, 0x00202000,
	0x10202008, 0x00200000, 0x00002008, 0x10000008,
	0x00200000, 0x10002000, 0x10000000, 0x00002008,
	0x10000008, 0x10202008, 0x00202000, 0x10200000,
	0x00202008, 0x10202000, 0x00000000, 0x10200008,
	0x00000008, 0x00002000, 0x10200000, 0x00202008,
	0x00002000, 0x00200008, 0x10002008, 0x00000000,
	0x10202000, 0x10000000, 0x00200008, 0x10002008,
	},
	{
	0x00100000, 0x02100001, 0x02000401, 0x00000000,
	0x00000400, 0x02000401, 0x00100401, 0x02100400,
	0x02100401, 0x00100000, 0x00000000, 0x02000001,
	0x00000001, 0x02000000, 0x02100001, 0x00000401,
	0x02000400, 0x00100401, 0x00100001, 0x02000400,
	0x02000001, 0x02100000, 0x02100400, 0x00100001,
	0x02100000, 0x00000400, 0x00000401, 0x02100401,
	0x00100400, 0x00000001, 0x02000000, 0x00100400,
	0x02000000, 0x00100400, 0x00100000, 0x02000401,
	0x02000401, 0x02100001, 0x02100001, 0x00000001,
	0x00100001, 0x02000000, 0x02000400, 0x00100000,
	0x02100400, 0x00000401, 0x00100401, 0x02100400,
	0x00000401, 0x02000001, 0x02100401, 0x02100000,
	0x00100400, 0x00000000, 0x00000001, 0x02100401,
	0x00000000, 0x00100401, 0x02100000, 0x00000400,
	0x02000001, 0x02000400, 0x00000400, 0x00100001,
	},
	{
	0x08000820, 0x00000800, 0x00020000, 0x08020820,
	0x08000000, 0x08000820, 0x00000020, 0x08000000,
	0x00020020, 0x08020000, 0x08020820, 0x00020800,
	0x08020800, 0x00020820, 0x00000800, 0x00000020,
	0x08020000, 0x08000020, 0x08000800, 0x00000820,
	0x00020800, 0x00020020, 0x08020020, 0x08020800,
	0x00000820, 0x00000000, 0x00000000, 0x08020020,
	0x08000020, 0x08000800, 0x00020820, 0x00020000,
	0x00020820, 0x00020000, 0x08020800, 0x00000800,
	0x00000020, 0x08020020, 0x00000800, 0x00020820,
	0x08000800, 0x00000020, 0x08000020, 0x08020000,
	0x08020020, 0x08000000, 0x00020000, 0x08000820,
	0x00000000, 0x08020820, 0x00020020, 0x08000020,
	0x08020000, 0x08000800, 0x08000820, 0x00000000,
	0x08020820, 0x00020800, 0x00020800, 0x00000820,
	0x00000820, 0x00020020, 0x08000000, 0x08020800,
	},
};

#define ps(i, j)	Psboxes[i][j]

#endif /* SMALL */

#if ASSEMBLY

extern void des_crypt();

#else

unsigned long Ip_l[] = {
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00000000,
	0x00000080,
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00008000,
	0x00008080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x00800000,
	0x00800080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00808000,
	0x00808080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80000000,
	0x80000080,
	0x80000000,
	0x80000080,
	0x80008000,
	0x80008080,
	0x80008000,
	0x80008080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
	0x80800000,
	0x80800080,
	0x80800000,
	0x80800080,
	0x80808000,
	0x80808080,
	0x80808000,
	0x80808080,
};
unsigned long Ip_r[] = {
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00000000,
	0x00000000,
	0x00000080,
	0x00000080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00008000,
	0x00008000,
	0x00008080,
	0x00008080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00800000,
	0x00800000,
	0x00800080,
	0x00800080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x00808000,
	0x00808000,
	0x00808080,
	0x00808080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80000000,
	0x80000000,
	0x80000080,
	0x80000080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80008000,
	0x80008000,
	0x80008080,
	0x80008080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80800000,
	0x80800000,
	0x80800080,
	0x80800080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
	0x80808000,
	0x80808000,
	0x80808080,
	0x80808080,
};
unsigned long Ip_inv_l[] = {
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
	0x00000000,
	0x80000000,
	0x00800000,
	0x80800000,
	0x00008000,
	0x80008000,
	0x00808000,
	0x80808000,
	0x00000080,
	0x80000080,
	0x00800080,
	0x80800080,
	0x00008080,
	0x80008080,
	0x00808080,
	0x80808080,
};
unsigned long Ip_inv_r[] = {
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x00000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x80000000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x00800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x80800000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x00008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x80008000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x00808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x80808000,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x00000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x80000080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x00800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x80800080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x00008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x80008080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x00808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
	0x80808080,
};


void des_crypt(char *block, int dflag)
{
	ulong l, r, l2, r2;
	uchar *s;
	int i;

	/* Initial Transpose */
	s = (uchar *)block;
	l = (((((((Ip_l[s[0]] >> 1
		  | Ip_l[s[1]]) >> 1
		 | Ip_l[s[2]]) >> 1
		| Ip_l[s[3]]) >> 1
	       | Ip_l[s[4]]) >> 1
	      | Ip_l[s[5]]) >> 1
	     | Ip_l[s[6]]) >> 1
	     | Ip_l[s[7]]);
	r = (((((((Ip_r[s[0]] >> 1
		  | Ip_r[s[1]]) >> 1
		 | Ip_r[s[2]]) >> 1
		| Ip_r[s[3]]) >> 1
	       | Ip_r[s[4]]) >> 1
	      | Ip_r[s[5]]) >> 1
	     | Ip_r[s[6]]) >> 1
	     | Ip_r[s[7]]);

	if (dflag == 0) {
		for (i = 0; i < 16; i++) {
			ulong v, x1, x2;

			/* E-transpose, Xor, S-box and P-transpose */
			x1 = rol1(r);
			x2 = ror4(x1) ^ Keys[i][0];
			x1 ^= Keys[i][1];
			v = l	^ ps(7, x1 & 0x3f)
				^ ps(5, (x1 >> 8) & 0x3f)
				^ ps(3, (x1 >> 16) & 0x3f)
				^ ps(1, (x1 >> 24) & 0x3f)
				^ ps(6, x2 & 0x3f)
				^ ps(4, (x2 >> 8) & 0x3f)
				^ ps(2, (x2 >> 16) & 0x3f)
				^ ps(0, (x2 >> 24) & 0x3f);
			l = r;
			r = v;
		}
	} else {
		for (i = 16; --i >= 0; ) {
			ulong v, x1, x2;

			/* E-transpose, Xor, S-box and P-transpose */
			x1 = rol1(r);
			x2 = ror4(x1) ^ Keys[i][0];
			x1 ^= Keys[i][1];
			v = l	^ ps(7, x1 & 0x3f)
				^ ps(5, (x1 >> 8) & 0x3f)
				^ ps(3, (x1 >> 16) & 0x3f)
				^ ps(1, (x1 >> 24) & 0x3f)
				^ ps(6, x2 & 0x3f)
				^ ps(4, (x2 >> 8) & 0x3f)
				^ ps(2, (x2 >> 16) & 0x3f)
				^ ps(0, (x2 >> 24) & 0x3f);
			l = r;
			r = v;
		}
	}
	/* Final transpose */
	l2 = (((((((Ip_inv_l[r & 0xff] >> 1
		   | Ip_inv_l[l & 0xff]) >> 1
		  | Ip_inv_l[r>>8 & 0xff]) >> 1
		 | Ip_inv_l[l>>8 & 0xff]) >> 1
		| Ip_inv_l[r>>16 & 0xff]) >> 1
	       | Ip_inv_l[l>>16 & 0xff]) >> 1
	      | Ip_inv_l[r>>24 & 0xff]) >> 1
	     | Ip_inv_l[l>>24 & 0xff]);
	r2 = (((((((Ip_inv_r[r & 0xff] >> 1
		   | Ip_inv_r[l & 0xff]) >> 1
		  | Ip_inv_r[r>>8 & 0xff]) >> 1
		 | Ip_inv_r[l>>8 & 0xff]) >> 1
		| Ip_inv_r[r>>16 & 0xff]) >> 1
	       | Ip_inv_r[l>>16 & 0xff]) >> 1
	      | Ip_inv_r[r>>24 & 0xff]) >> 1
	     | Ip_inv_r[l>>24 & 0xff]);
	*block++ = (char)(l2 >> 24);
	*block++ = (char)(l2 >> 16);
	*block++ = (char)(l2 >> 8);
	*block++ = (char)l2;
	*block++ = (char)(r2 >> 24);
	*block++ = (char)(r2 >> 16);
	*block++ = (char)(r2 >> 8);
	*block++ = (char)r2;
}
#endif /* ASSEMBLY */


int ecb_crypt(char *key, char *buf, unsigned len, unsigned mode)
{
	des_setkey(key);
	for (len = (len + 7) & ~7; len != 0; buf += 8, len -= 8)
		des_crypt(buf, mode & DES_DIRMASK);
	return ((mode & DES_DEVMASK) == DES_SW ? DESERR_NONE
					       : DESERR_NOHWDEVICE);
}


int cbc_crypt(char *key, char *buf, unsigned len, unsigned mode, char *ivec)
{
	char nvec[8];

	des_setkey(key);
	switch (mode & DES_DIRMASK) {
	case DES_ENCRYPT:
		for (len = (len + 7) & ~7; len != 0; len -= 8) {
			buf[0] ^= ivec[0];
			buf[1] ^= ivec[1];
			buf[2] ^= ivec[2];
			buf[3] ^= ivec[3];
			buf[4] ^= ivec[4];
			buf[5] ^= ivec[5];
			buf[6] ^= ivec[6];
			buf[7] ^= ivec[7];
			des_crypt(buf, DES_ENCRYPT);
			ivec[0] = *buf++;
			ivec[1] = *buf++;
			ivec[2] = *buf++;
			ivec[3] = *buf++;
			ivec[4] = *buf++;
			ivec[5] = *buf++;
			ivec[6] = *buf++;
			ivec[7] = *buf++;
		} 
		break;
	case DES_DECRYPT:
		for (len = (len + 7) & ~7; len != 0; len -= 8) {
			nvec[0] = buf[0];
			nvec[1] = buf[1];
			nvec[2] = buf[2];
			nvec[3] = buf[3];
			nvec[4] = buf[4];
			nvec[5] = buf[5];
			nvec[6] = buf[6];
			nvec[7] = buf[7];
			des_crypt(buf, DES_DECRYPT);
			*buf++ ^= ivec[0];
			*buf++ ^= ivec[1];
			*buf++ ^= ivec[2];
			*buf++ ^= ivec[3];
			*buf++ ^= ivec[4];
			*buf++ ^= ivec[5];
			*buf++ ^= ivec[6];
			*buf++ ^= ivec[7];
			ivec[0] = nvec[0];
			ivec[1] = nvec[1];
			ivec[2] = nvec[2];
			ivec[3] = nvec[3];
			ivec[4] = nvec[4];
			ivec[5] = nvec[5];
			ivec[6] = nvec[6];
			ivec[7] = nvec[7];
		}
		break;
	}
	return ((mode & DES_DEVMASK) == DES_SW ? DESERR_NONE
					       : DESERR_NOHWDEVICE);
}
